#pragma once

#include "Serializable.h"

#include <boost/noncopyable.hpp>

namespace events {

namespace helpers {

// Generic versions of "write" and "read" functions are implemented
// here, and can be redefined (in same namespace) by users for specific
// types

template<typename T>
void saveToStream(std::ostream &os, const T& t) {
	os.write(reinterpret_cast<const char*>(&t), sizeof(T));
}

template<typename T>
void readFromStream(std::istream &is,  T *pt) {
	is.read(reinterpret_cast<char*>(pt), sizeof(T));
}


template<typename T>
void writeDebugInfo(std::ostream &os, const T& t) {
	os << t;
};

}  // end namespace "helpers"


//
// This class defines "serializable" data types,
// which are wrappers to basic types
//


/**
 * Generic template class, which can be used as a wrapper
 * for any given (primitive) type
 */
template<typename T>
class GenericDataType : public platform::ISerializable, private boost::noncopyable {
public:
	// this function can be used as a clenup function,
	// called for the _t parameter
	typedef void (*func_cleaner)(T&);

private:
	T _t;
	func_cleaner _fc;

public:
	inline GenericDataType(func_cleaner fc = NULL) : _t(), _fc(fc) {}
	inline GenericDataType(const T &t, func_cleaner fc = NULL) : _t(t), _fc(fc) {}
	inline ~GenericDataType(void) { if (_fc != NULL) _fc(_t); }

	inline void set(const T &t) { _t = t; }
	inline GenericDataType & operator=(const T &t) { set(t); return *this; }
	inline const T & get(void) const { return _t; }
	inline const T & operator()(void) const { return get(); }

	virtual void saveToStream(std::ostream &os) const { helpers::saveToStream(os, _t); }

	virtual void readFromStream(std::istream &is) { helpers::readFromStream(is, &_t); }

	virtual void writeDebugInfo(std::ostream &os) const { helpers::writeDebugInfo(os, _t); }

};


}  // end namespace
